//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#include "ExtendedFASTAFileMotif.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#include <fstream>
#include <iostream>
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
#define LENGTHLINE 5000
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
using namespace std;
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ExtendedFASTAFileMotif::ExtendedFASTAFileMotif() {
  this->filenameFASTAIn = new String();
  this->filenameMotifIn = new String();
  this->filenameOut     = new String();
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ExtendedFASTAFileMotif::ExtendedFASTAFileMotif(const ExtendedFASTAFileMotif& extendedFASTAFileMotif) {
  this->filenameFASTAIn = new String(extendedFASTAFileMotif.filenameFASTAIn);
  this->filenameMotifIn = new String(extendedFASTAFileMotif.filenameMotifIn);
  this->filenameOut     = new String(extendedFASTAFileMotif.filenameOut);
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ExtendedFASTAFileMotif::ExtendedFASTAFileMotif(const ExtendedFASTAFileMotif* extendedFASTAFileMotif) {
  this->filenameFASTAIn = new String(extendedFASTAFileMotif->filenameFASTAIn);
  this->filenameMotifIn = new String(extendedFASTAFileMotif->filenameMotifIn);
  this->filenameOut     = new String(extendedFASTAFileMotif->filenameOut);
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
ExtendedFASTAFileMotif::~ExtendedFASTAFileMotif() {
  if (this->filenameFASTAIn) delete this->filenameFASTAIn;
  if (this->filenameMotifIn) delete this->filenameMotifIn;
  if (this->filenameOut)     delete this->filenameOut;
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ExtendedFASTAFileMotif::FilenameFASTAIn(String* filenameFASTAIn) {
  if (filenameFASTAIn) {
    if (this->filenameFASTAIn) delete this->filenameFASTAIn;
    this->filenameFASTAIn = filenameFASTAIn;
  }
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ExtendedFASTAFileMotif::FilenameMotifIn(String* filenameMotifIn) {
  if (filenameMotifIn) {
    if (this->filenameMotifIn) delete this->filenameMotifIn;
    this->filenameMotifIn = filenameMotifIn;
  }
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
void ExtendedFASTAFileMotif::FilenameOut(String* filenameOut) {
  if (filenameOut) {
    if (this->filenameOut) delete this->filenameOut;
    this->filenameOut = filenameOut;
  }
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* ExtendedFASTAFileMotif::FilenameFASTAIn(void) {
  return this->filenameFASTAIn;
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* ExtendedFASTAFileMotif::FilenameMotifIn(void) {
  return this->filenameMotifIn;
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
String* ExtendedFASTAFileMotif::FilenameOut(void) {
  return this->filenameOut;
}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ExtendedFASTAFileMotif::GetExtendedFileWithMotifSequence() {
    
  if (!this->filenameFASTAIn || !this->filenameMotifIn || !this->filenameOut) return false;

  fstream fileFASTA;
  fstream fileMotif;
  fstream fileOut;

  fileFASTA.open(this->filenameFASTAIn->Out(), fstream::in);
  fileOut.open(this->filenameOut->Out(), fstream::out);

  char    buffer[LENGTHLINE + 1],  bufferBefore[LENGTHLINE + 1];
  char    buffer1[LENGTHLINE + 1], bufferBefore1[LENGTHLINE + 1];

  bool    flag  = false;
  bool    flag1 = false;
  
  String* line = new String();
  String* line1 = new String();

  String* sequence  = new String();
  String* sequenceM = new String();

  TListE <String>* listPDBId = new TListE <String> ();
  TListE <String>* listParts = new TListE <String> ();

  while (!fileFASTA.eof()) {

    fileFASTA.getline(buffer, LENGTHLINE);

    if (flag) {

      cout << "Processing :" << bufferBefore << endl;
        
      line->In(bufferBefore);
      line->In(' ', 0);
      line->RTrim();

      listPDBId->Clear();
      this->SplitColumn(line->Out(), listPDBId, ",");

      if (listPDBId->Length()) {

        cout << "Searching:" << listPDBId->Get(0)->Out() << endl;

        char temporalPDBID[strlen(listPDBId->Get(0)->Out()) + 1];
        strcpy(temporalPDBID, listPDBId->Get(0)->Out());

        listParts->Clear();
        this->SplitColumn(temporalPDBID, listParts, "_");

        if (listParts->Length()) {

          fileMotif.open(this->filenameMotifIn->Out(), fstream::in);
          
          flag1 = false;

          while (!fileMotif.eof()) {

            fileMotif.getline(buffer1, LENGTHLINE);

            if (flag1) {

              line1->In(bufferBefore1);

              if (line1->Contain(listParts->Get(0)->Out())) {

                listPDBId->SetInitial();

                while (listPDBId->SetNext()) {
                  fileOut << ">" << listPDBId->GetCurrent()->Out() << endl;
                  fileOut << buffer1 << endl;
                }

                break;

              }

            }

            flag1 = (flag1)?false:true;
            strcpy(bufferBefore1, buffer1);

          }

          fileMotif.close();

        }

      }
        
    }

    flag = (flag)?false:true;

    strcpy(bufferBefore, buffer);

  }

  fileFASTA.close();
  fileOut.close();

  if (sequence)  delete sequence;
  if (sequenceM) delete sequenceM;

  if (line)      delete line;
  if (line1)     delete line1;

  if (listPDBId) delete listPDBId;
  if (listParts) delete listParts;

  return true;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ExtendedFASTAFileMotif::GetExtendedFileFASTA() {

  if (!this->filenameFASTAIn || !this->filenameOut) return false;

  fstream fileFASTA;
  fstream fileOut;

  fileFASTA.open(this->filenameFASTAIn->Out(), fstream::in);
  fileOut.open(this->filenameOut->Out(), fstream::out);

  char              buffer[LENGTHLINE + 1],  bufferBefore[LENGTHLINE + 1];

  bool              flag  = false;
  String*           line = new String();
  String*           sequence  = new String();
  TListE <String>*  listPDBId = new TListE <String> ();

  while (!fileFASTA.eof()) {
    fileFASTA.getline(buffer, LENGTHLINE);
    if (flag) {
      cout << "Processing :" << bufferBefore << endl;
      line->In(bufferBefore);
      line->In(' ', 0);
      line->RTrim();
      listPDBId->Clear();
      this->SplitColumn(line->Out(), listPDBId, ",");
      if (listPDBId->Length()) {
        listPDBId->SetInitial();
        while (listPDBId->SetNext()) 
          fileOut << ">" << listPDBId->GetCurrent()->Out() << endl << buffer << endl;
      }
    }

    flag = (flag)?false:true;
    strcpy(bufferBefore, buffer);
  }

  fileFASTA.close();
  fileOut.close();

  if (sequence)  delete sequence;
  if (line)      delete line;
  if (listPDBId) delete listPDBId;

  return true;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ExtendedFASTAFileMotif::SplitColumn(char* buffer, TListE<String>* columns, char* characters) {

  if (!buffer || !columns || !characters) return false;

  char *part = strtok(buffer, characters);

  while (part) {
    String* cell = new String(part);
    cell->Trim();
    columns->Add(cell);
    part = strtok(NULL, characters);
  }

  return true;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
bool ExtendedFASTAFileMotif::SplitColumn(char* buffer, TListE<String>* columns, const char* characters) {

  if (!buffer || !columns || !characters) return false;

  char *part = strtok(buffer, characters);

  while (part) {
    String* cell = new String(part);
    cell->Trim();
    columns->Add(cell);
    part = strtok(NULL, characters);
  }

  return true;

}
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
//---------------------------------------------------------------------------------------------------------------------------------------------------------//
